using UnityEngine;
using System.Collections;
using System;

public class IMIBodyMeaTool/* : Singleton<IMIBodyMeaTool>*/
{


//	private float[,] waistTable=new float[6,15]{
//	 //  18, 19, 20, 21, 22  23  24  25  26  27  28  29  30  31  32
//		{72, 73, 74, 75, 77, 80 ,82, 83, 83, 84, 85, 86, 87, 89, 90  } ,            //
//		{74, 75, 77, 78, 79, 82, 84, 85, 86, 87, 88, 90, 91, 92, 93 },
//		{76, 78, 82, 83, 84, 86, 88, 90, 91, 91, 92, 93, 94, 94, 95 } ,
//		{78, 80, 85, 82, 85, 88, 90, 92, 93, 94, 94, 95, 100,101,103},
//		{80, 83, 86, 88, 90, 91, 92, 98, 105,105,106,108,110,111,112   },
//		{83, 87, 89, 90, 91, 93, 95,102, 108,109,110,113,115,116,118} 
//	};


	private static float[,] waistTable=new float[11,15]{
	 //  18, 19, 20, 21, 22  23  24  25  26  27  28  29  30      31  32
		{72, 73, 74, 75, 77, 80 ,82, 83, 83, 84, 85, 86, 87,     89, 90  } ,   //26
		{73, 74, 75, 76, 78, 81 ,83, 84, 85, 86, 87, 88, 89,     90, 91  } ,  //27
		{74, 75, 77, 78, 79, 82, 84, 85, 86, 87, 88, 90, 91,     92, 93 },    //28
		{75, 77, 80, 80, 82, 84, 86, 87, 89, 90, 90, 92, 93,     94, 96 } ,   //29
		{76, 78, 82, 83, 84, 86, 88, 90, 91, 92, 92, 94, 95,     97, 99 } ,    //30
		{76, 79, 84, 84, 85, 87, 89, 92, 93, 95, 96, 97, 98,     99,102},      //31                                                                 //31  
		{78, 80, 85, 85, 85, 88, 91, 94, 96, 98, 99, 99, 100,    101,104},      //32
		{79, 81, 85, 86, 87, 90, 93, 96, 98, 101,102,103,104,    106,108 },   //33
		{80, 83, 86, 88, 90, 92, 95, 98, 101,104,106,108,108,    110,112 },    //34
		{82, 85, 88, 89, 91, 93, 96,100, 103,106,108,110,111,    113,115},    //35
		{83, 87, 89, 90, 91, 94, 97,102, 105,108,110,113,115,    116,118}        //36
	};


	private static float[,] HipsTable=new float[13,13]{
		//  20,     21,     22,     23,     24      25      26      27      28      29      30      31      32   
		{83  ,	85  ,	87  ,	89  ,   91  ,	93  ,	95  ,	97  ,	98  ,	101 ,	104 ,	106 ,	108 },  //30
		{85  ,	87  ,	89  ,	91  ,   93  ,	95  ,	97  ,	98  ,	99 	,   102 ,	104 ,	106 ,	109 },
		{87  ,	89  ,	90  ,	92  ,   94  ,	96  ,	98  ,	99  ,	100 ,	102 ,	104 ,	107 ,	109 },  //32
		{88  ,	90  ,	91  ,	93  ,   95  ,	97  ,	99  ,	100 ,	101 ,	103 ,	105 ,	107 ,	110 },
		{88  ,	90  ,	92  ,	94  ,   95  ,	97  ,	100 ,	101 ,	102 ,	104 ,	105 ,	108 ,	110 },   //34
		{89  ,	91  ,	93  ,	95  ,   96  ,	98  ,	100 ,	101 ,	102 ,	104 ,	105 ,	108 ,	111 },
		{90  ,	92  ,	94  ,	95  ,   96  ,	98  ,	100 ,	101 ,	102 ,	104 ,	105 ,	109 ,	112 },  //36
		{91  ,	93  ,	95  ,	96 ,    97  ,	99  ,	101 ,	102 ,	104 ,	105 ,	107 ,	110 ,	113 },
		{92  ,	94  ,	96  ,	97  ,   98  ,	99  ,	102 ,	104 ,	106 ,	107 ,	108 ,	111 ,	114 },   //38
		{93  ,	95  ,	97  ,	98  ,   99  ,	101 ,	104 ,	106 ,	108 ,	109 ,	110 ,	113 ,	115 },
		{94  ,	96  ,	98  ,	99  ,   100 ,	103 ,	105 ,	107 ,	110 ,	111 ,	112 ,	114 ,	116 },   //40
		{94  ,	97  ,	99  ,	100  ,   102 ,	104 ,	106 ,	108 ,	110 ,	112 ,	114 ,	115 ,	117 },
		{95  ,	98  ,	100  ,	101  ,   103 ,	105 ,	107 ,	109 ,	111 ,	113 ,	116 ,	117 ,	118 }	//42
		
	};







#region bodyheight
	public static float GetHeightByHeadTopPixPos(int depthh, int depthw , float tiltDownAngle, float verticalFov,int headTopPixPosY, int headTopDepth , float setDeviceHeight,float offsetY )
	{
		return GetHeightByHeadTopPixPosRealize( depthh,  depthw ,  tiltDownAngle,  verticalFov, headTopPixPosY,  headTopDepth ,  setDeviceHeight,offsetY );
	}


	private static float GetHeightByHeadTopPixPosRealize(int depthh, int depthw , float tiltDownAngle, float verticalFov,int headTopPixPosY, int headTopDepth , float setDeviceHeight,float offsetY )
	{
		
		float bodyHeight=0f;
		
		//This is the y pix pos of vertical plane, which tile angle equals tiltDownAngle
		int VerticalPlanePixPosY= depthh/2-  
			(int)(Mathf.Tan( Mathf.Deg2Rad*tiltDownAngle)/Mathf.Tan( Mathf.Deg2Rad*verticalFov/2)*((float)(depthh/2)));
		
		
		float HeightDiff  =Mathf.Abs(    
		                             Mathf.Cos( Mathf.Deg2Rad*tiltDownAngle)*Mathf.Tan(Mathf.Deg2Rad*tiltDownAngle)*
		                             ((float)(headTopDepth))*
		                             ((float)(headTopPixPosY-VerticalPlanePixPosY))/((float)(depthh/2-VerticalPlanePixPosY))
		                             );


//		Debug.LogWarning( "===========HeightDiff "+ HeightDiff.ToString()+
//		                  "====headTopDepth "+ headTopDepth.ToString()+
//		                  "====VerticalPlanePixPosY "+ VerticalPlanePixPosY.ToString()+
//		                  "==headTopPixPosY "+ headTopPixPosY.ToString());


		if(headTopPixPosY>VerticalPlanePixPosY)   //the guy is lower than setDeviceHeight
		{		
			bodyHeight=setDeviceHeight-HeightDiff+offsetY;
		}
		else    // the guy is higher than setDeviceHeight
		{
			bodyHeight=setDeviceHeight+HeightDiff+offsetY;
		}
		
		return bodyHeight;		
	}


	public static int GetHead2TopPixDist (ushort[] depthPlayerData, int depthW, int depthH, int OrigHeaddepthMapPixX, int OrigHeaddepthMapPixY, int boundThreshval)
	{
		return GetHead2TopPixDistRealize (depthPlayerData, depthW, depthH, OrigHeaddepthMapPixX, OrigHeaddepthMapPixY, boundThreshval);
	}
	//using depthPlayerData. For getting depthvalue, we need bo >>3
	private static int GetHead2TopPixDistRealize (ushort[] depthPlayerData, int depthW, int depthH, int OrigHeaddepthMapPixX, int OrigHeaddepthMapPixY, int boundThreshval)
	{
		// if the depth val of high point is larger than the head point by this value,  we  regard that point as a backpoint.  
		//ushort threshval = 60; //mm
		int dist = 0;
		int headX = OrigHeaddepthMapPixX;
		int headY = OrigHeaddepthMapPixY;
		int headOrigIdx = headY * depthW + headX;
		//the idx which is higher than the head;
		int headHighIdx = headOrigIdx;
		//Compare the point higher than the certain point/head point, one pix by one pix. Until we found the one on the border of the contour.
		while((headHighIdx>=depthW)&&
		      (headHighIdx<depthW*depthH) 

		      ){
			if (Mathf.Abs ((depthPlayerData [headHighIdx - depthW]>>3) - (depthPlayerData [headOrigIdx]>>3)) > boundThreshval) {
				return dist;
			}
			dist++;
			headHighIdx -= depthW;
			
		}
		return dist;
	}

#endregion;


#region Pixel Line Analysis

	//	//Get the smallest boundary end of a contour, we call it min, because we do not know it left or right.
	//	//We only know it as the smallest X index point of a row
	public static  Vector2 GetContourMinEnd (int depthW, int depthH,  int pixposx,int pixposy, ushort[] _depthPlayerData, ushort boundThreshval)
	{
		return GetContourMinEndRealize ( depthW,  depthH,   pixposx, pixposy,  _depthPlayerData,  boundThreshval);
	}

	private static  Vector2 GetContourMinEndRealize (int depthW, int depthH,  int pixposx,int pixposy, ushort[] _depthPlayerData, ushort boundThreshval)
	{
		int origY = pixposy;
		if (origY < 1) {
			origY = 1;
		}
		if (origY > depthH - 1) {
			origY = depthH - 1;
		}
		
		int origX = pixposx;
		
		if (origX <= 1) {
			return new Vector2 (-1, origY);
		}
		
		
		int minEnd = 0;



		//before 11 18  stopped when meeting sharp change.  this sometimes problem for sharp change not always occurs.
//		for (int i=origX; i>1; i--) {  
//			minEnd = i;
//			
//			//			Debug.Log("line depth a---------------------------------------------------"+ (_depthPlayerData [origY * depthW + i]>>3).ToString());
//			//			Debug.Log("line depth b---------------------------------------------------"+ (_depthPlayerData [origY * depthW + i-1]>>3).ToString());
//			//			
//			if(
//				 (Math.Abs ((_depthPlayerData [origY * depthW + i]>>3) - (_depthPlayerData [origY * depthW + i - 1]>>3)) > boundThreshval)
//				//||
//				//((DoesPixBelongToPlayers(depthW,depthH,i,origY,_depthPlayerData))&&(! DoesPixBelongToPlayers(depthW,depthH,i-1,origY,_depthPlayerData)  ))                         
//			  ) 
//			{
//				return new Vector2 (minEnd, origY);
//			}
//		}


//After 11 18 , use a more complicated method, which use the extension several pixels. 

		bool isInExtensionWindow=false;
		int extensionPixCount=0;
		int extensionPixSum=8;

		int playerIdx=((_depthPlayerData  [pixposy *depthW +pixposx]) & 7);

		for (int i=origX; i>1; i--) {
			if(isInExtensionWindow)
			{
				extensionPixCount++;
				if( extensionPixCount> extensionPixSum )
				{
//					if(minEnd<50)
//						Debug.Log("Return after extensionPixCount is full  "+ minEnd.ToString()+"  playidx   " +playerIdx.ToString());
//					
					return new Vector2 (minEnd, origY);
				}

				if((_depthPlayerData [origY * depthW + i]&7)==playerIdx)
				{
					isInExtensionWindow=false;
					extensionPixCount=0;
				}
				else
				{
					if(
						(Math.Abs ((_depthPlayerData [origY * depthW + i]>>3) - (_depthPlayerData [origY * depthW + i - 1]>>3)) > boundThreshval)
						) 
					{
						minEnd = i;

//						if(minEnd<50)
//						{
//						Debug.Log("Return during steep fall in ExtensionWindow   "+ i.ToString());	
//						}
						
						return new Vector2 (minEnd, origY);

					} 
				         
				}
			}
			else
			{
				minEnd = i;
				if(
					((_depthPlayerData [origY * depthW + i]&7)==playerIdx)&&
				    ((_depthPlayerData [origY * depthW + i-1]&7)!=playerIdx)
					)
				{
					isInExtensionWindow=true;
					  extensionPixCount=0;

//					if(minEnd<50)
//						Debug.Log("Meet a player pix change  "+ minEnd.ToString());
				}
			}
		}
		//Debug.Log("Return at the end");


		if(minEnd>15)
		{
		   return new Vector2 (minEnd, origY);
		}
		else
		{
		   return new Vector2 (-1, origY);
			
		}
	}



	public static  Vector2 GetContourMaxEnd (int depthW, int depthH,  int pixposx,int pixposy, ushort[] _depthPlayerData, ushort boundThreshval)
	{
		return GetContourMaxEndRealize(depthW, depthH,  pixposx, pixposy,  _depthPlayerData, boundThreshval);
	}


	//	//Get the max point in the same row of a certain point
	private static  Vector2 GetContourMaxEndRealize (int depthW, int depthH,  int pixposx,int pixposy, ushort[] _depthPlayerData, ushort boundThreshval)
	{
		int origY = pixposy;
		if (origY < 1) {
			origY = 1;
		}
		if (origY > depthH - 1) {
			origY = depthH - 1;
		}
		
		int origX = pixposx;
		
		if (origX >= depthW - 2) {
			return new Vector2 (depthW - 2, origY);
		}
		
		int maxEnd = 0;



		//before 11 18  stopped when meeting sharp change.  this sometimes problem for sharp change not always occurs.

//		for (int j=origX; j<depthW-2; j++) {
//			maxEnd = j;
//			  
//			if (
//				 (Math.Abs ((_depthPlayerData [origY * depthW + j]>>3)- 
//			              (_depthPlayerData [origY * depthW + j + 1]>>3))    > boundThreshval)
//				//||
//				//(((DoesPixBelongToPlayers(depthW,depthH,j,origY,_depthPlayerData))&&(! DoesPixBelongToPlayers(depthW,depthH,j+1,origY,_depthPlayerData)  )))
//			    ) 
//			{
//				return new Vector2 (maxEnd, origY);
//			}
//		}


//After 11 18 , use a more complicated method, which use the extension several pixels. 

		bool isInExtensionWindow=false;
		int extensionPixCount=0;
		int extensionPixSum=8;
		
		int playerIdx= ( (_depthPlayerData  [pixposy *depthW +pixposx]) & 7);
		
		for(int j=origX; j<depthW-2; j++)  {
			if(isInExtensionWindow)
			{
				extensionPixCount++;
				if( extensionPixCount> extensionPixSum )
				{
					//					if(minEnd<50)
					//						Debug.Log("Return after extensionPixCount is full  "+ minEnd.ToString()+"  playidx   " +playerIdx.ToString());
					//					
					return new Vector2 (maxEnd, origY);
				}

				if((_depthPlayerData [origY * depthW + j]&7)==playerIdx)
				{
					isInExtensionWindow=false;
					extensionPixCount=0;
				}
				else
				{
					if(
						(Math.Abs ((_depthPlayerData [origY * depthW + j]>>3) - (_depthPlayerData [origY * depthW + j + 1]>>3)) > boundThreshval)
						) 
					{
						maxEnd = j;
						
						//						if(minEnd<50)
						//						{
						//						Debug.Log("Return during steep fall in ExtensionWindow   "+ i.ToString());	
						//						}
						
						return new Vector2 (maxEnd, origY);
						
					} 
					
				}
			}
			else
			{
				maxEnd = j;
				if(
					((_depthPlayerData [origY * depthW + j]&7)==playerIdx)&&
					((_depthPlayerData [origY * depthW + j+1]&7)!=playerIdx)
					)
				{
					isInExtensionWindow=true;
					extensionPixCount=0;
					
					//					if(minEnd<50)
					//						Debug.Log("Meet a player pix change  "+ minEnd.ToString());
				}
			}
		}
		//Debug.Log("Return at the end");
		
		
		if(maxEnd<depthW-15)
		{
			return new Vector2 (maxEnd, origY);
		}
		else
		{
			return new Vector2 (-1, origY);
			
		}

		return new Vector2 (maxEnd, origY);
	}



	public static void GetFinalFrontEnds(int depthW, int depthH,ushort[] _depthPlayerDataOriginal, 
	                                     Vector2 WaistMidPixPos,   Vector3 MinWaistPixPos,Vector3 MaxWaistPixPos, 
	                                     ref Vector2 resultWaistEndMin, 
	                                     ref Vector2 resultWaistEndMax, float diminishRatio,float extendRatio)
	{
		GetFinalFrontEndsRealize(depthW,  depthH,_depthPlayerDataOriginal,
		                         WaistMidPixPos, MinWaistPixPos, MaxWaistPixPos, 
		                         ref resultWaistEndMin, 
		                         ref resultWaistEndMax,  diminishRatio, extendRatio);
	}



	private static void GetFinalFrontEndsRealize(int depthW, int depthH,ushort[] _depthPlayerDataOriginal, 
	                                             Vector2 WaistMidPixPos, Vector3 MinWaistPixPos,Vector3 MaxWaistPixPos, 
	                                             ref Vector2 resultWaistEndMin, 
	                                             ref Vector2 resultWaistEndMax,
	                                             float diminishRatio,float extendRatio)
	{
		//The way we use to get front waist length, which is by sobel function, does not work properly.
		//So we use a simpler say to get  resultWaistEnds


		//before  11,24 , with the assumption that  player should stick their hands  tight to the sides of their bodies.
//		float waistLineDiff =Mathf.Abs(MaxWaistPixPos.x - MinWaistPixPos.x);
//		resultWaistEndMin.x = MinWaistPixPos.x + waistLineDiff / 7.3f;
//		resultWaistEndMax.x = MaxWaistPixPos.x - waistLineDiff / 7.3f;
//		resultWaistEndMin.y = MinWaistPixPos.y; 
//		resultWaistEndMax.y = MaxWaistPixPos.y;

		//After 11,24.  Solve the problem that hands not stick to the sides of the body , but leave some hole inside.
		int tempPlayerIndex1 = _depthPlayerDataOriginal [(int)WaistMidPixPos.y *depthW +(int)WaistMidPixPos.x] & 7;
		Debug.Log("Waist middle player indx ---------------------  "+ tempPlayerIndex1.ToString() );


		bool isRealMinEnd=true;
		for(int i=0;i<50;i++)
		{
			//The  MinWaistPixPos.x  itself is a player mark. So we must -1, then we - i
			if((MinWaistPixPos.x-1-i)<=1)
			{
				break;
			}

			if(( _depthPlayerDataOriginal [(int)MinWaistPixPos.y *depthW +(int)MinWaistPixPos.x-1-i] & 7)==(tempPlayerIndex1))
			{
	             //	Debug.Log("Waist middle player indx ---------------------  "+ tempPlayerIndex1.ToString() );
				
				isRealMinEnd=false;
				break;
			}
		}

		if(isRealMinEnd)
		{		
			float waistLineDiff =Mathf.Abs(WaistMidPixPos.x - MinWaistPixPos.x);

			resultWaistEndMin.x = MinWaistPixPos.x + waistLineDiff / diminishRatio;//3.6f;
		}
		else
		{
			float waistLineDiff =Mathf.Abs(WaistMidPixPos.x - MinWaistPixPos.x);

			resultWaistEndMin.x = MinWaistPixPos.x- waistLineDiff / extendRatio;//9f;
		}

		bool isRealMaxEnd=true;
		for(int i=0;i<50;i++)
		{
			if((MaxWaistPixPos.x+1+i)>=depthW-2)
			{
				break;
			}
			
			if(( _depthPlayerDataOriginal [(int)MaxWaistPixPos.y *depthW +(int)MaxWaistPixPos.x+1+i] & 7)==(tempPlayerIndex1))
			{
				isRealMaxEnd=false;
				break;
			}
		}
		if(isRealMaxEnd)
		{
			float waistLineDiff =Mathf.Abs(MaxWaistPixPos.x-WaistMidPixPos.x );
			resultWaistEndMax.x = MaxWaistPixPos.x -waistLineDiff /diminishRatio;// 3.6f;
		}
		else
		{
			float waistLineDiff =Mathf.Abs(MaxWaistPixPos.x-WaistMidPixPos.x );

			resultWaistEndMax.x = MaxWaistPixPos.x+waistLineDiff /extendRatio;//9f; ;		
		}

		resultWaistEndMin.y = MinWaistPixPos.y; 
		resultWaistEndMax.y = MaxWaistPixPos.y;

	}





	public static void GetThickestPixPosesByDepth( int depthW, int depthH, Vector2 jointPixPos0,Vector2 jointPixPos1, 
	                                     ref Vector2 minEnd , ref Vector2 maxEnd ,
	                                              ushort[] _depthPlayerData,ushort boundaryThreshVal)
	{
		GetThickestPixPosesByDepthRealize(  depthW,  depthH,  jointPixPos0, jointPixPos1, 
		                                  ref  minEnd , ref  maxEnd ,
		                                  _depthPlayerData, boundaryThreshVal);
	}


	private static void GetThickestPixPosesByDepthRealize( int depthW, int depthH, Vector2 jointPixPos0,Vector2 jointPixPos1, 
	                                              ref Vector2 minEnd , ref Vector2 maxEnd ,
	                                              ushort[] _depthPlayerData,ushort boundaryThreshVal)
	{
		Vector2 pixposMin=Vector2.zero;
		Vector2 pixposMax=Vector2.zero;
		if(jointPixPos0.y<jointPixPos1.y)
		{
			pixposMin=jointPixPos0;
			pixposMax=jointPixPos1;
		}
		else
		{
			pixposMin=jointPixPos1;
			pixposMax=jointPixPos0;
		}
		
		int minY=(int)pixposMin.y;
		int maxY=(int)pixposMax.y;
		int minX=(int)pixposMin.x;
		int maxX=(int)pixposMax.x;
		
		float XAddedValue=((float)(maxX-minX))/((float)(maxY-minY));
		
		//Debug.Log("XAddedValue----------------------------------------------"+XAddedValue.ToString() );
		float Xaccu=(float)minX;
		
		
		
		Vector2 resultMin = GetContourMinEnd(depthW,depthH,(int)pixposMin.x,  (int)pixposMin.y, 
		                                     _depthPlayerData,boundaryThreshVal);

//		Debug.Log("beginning pixPosMin  " + pixposMin.x.ToString()  );
//		
//		Debug.Log("beginning resultMin  " + resultMin.x.ToString()  );

		Vector2 resultMax = GetContourMaxEnd (depthW,depthH,(int)pixposMin.x, (int)pixposMin.y, 
		                                      _depthPlayerData,boundaryThreshVal);
		int currWidth=(int)Math.Abs(resultMin.x-resultMax.x)  ;
		for(int i=minY;i<maxY;i++)
		{
			int tmpy=i;
			int tmpx=(int)Xaccu;
			Vector2 end0 = GetContourMinEnd (depthW,depthH,tmpx,tmpy, 
			                                 _depthPlayerData,boundaryThreshVal);

						//Debug.Log("end0  " + end0.x.ToString()  );

			Vector2 end1 = GetContourMaxEnd (depthW,depthH,tmpx,tmpy, 
			                                 _depthPlayerData,boundaryThreshVal);




			int tmpWW=0;

			if((end0.x>20)&&(end0.x< depthW-20)&&
			   (end1.x>20)&&(end1.x< depthW-20)
			   )
			{
				tmpWW=(int)Math.Abs(end0.x-end1.x)  ;
			}
			if(tmpWW>currWidth)
			{
				resultMin=end0;
				resultMax=end1;
				currWidth=tmpWW;
			}
			//Xaccu+=XAddedValue;
		}
		minEnd=resultMin;
		maxEnd=resultMax;

		if(minEnd.x<50)
		{
			int playeridx0=	(_depthPlayerData  [((int)(jointPixPos0.y)) *depthW +((int)(jointPixPos0.x))]) & 7;
			int playeridx1=	(_depthPlayerData  [((int)(jointPixPos1.y)) *depthW +((int)(jointPixPos1.x))]) & 7;

			Debug.Log("-------------------------------------------------------player idx  "+playeridx0.ToString()+"----------:   "+playeridx1.ToString());
			Debug.Log("-------------------------------------------------------result Ends MIn  "+((int)(minEnd.x)).ToString()+"-------Max:   "+((int)(maxEnd.x)).ToString());
		}

		if(maxEnd.x>depthW- 50)
		{
			int playeridx0=	(_depthPlayerData  [((int)(jointPixPos0.y)) *depthW +((int)(jointPixPos0.x))]) & 7;
			int playeridx1=	(_depthPlayerData  [((int)(jointPixPos1.y)) *depthW +((int)(jointPixPos1.x))]) & 7;
			
			Debug.Log("-------------------------------------------------------player idx  "+playeridx0.ToString()+"----------:   "+playeridx1.ToString());
			Debug.Log("-------------------------------------------------------result Ends max  "+((int)(minEnd.x)).ToString()+"-------Max:   "+((int)(maxEnd.x)).ToString());
		}

	}
	



	public static void GetArrOfPixPosesOfThicknessEndsInHeightRange( int depthW, int depthH, Vector2 jointPixPos0,Vector2 jointPixPos1, 
	                                             ref  ArrayList thickEndsArr ,
	                                              ushort[] _depthPlayerData,ushort boundaryThreshVal)
	{
		GetArrOfPixPosesOfThicknessEndsInHeightRangeRealize(  depthW,  depthH,  jointPixPos0, jointPixPos1, 
		                                                  ref   thickEndsArr ,
		                                  _depthPlayerData, boundaryThreshVal);
	}
	
	
	private static void GetArrOfPixPosesOfThicknessEndsInHeightRangeRealize( int depthW, int depthH, Vector2 jointPixPos0,Vector2 jointPixPos1, 
	                                                                     ref   ArrayList thickEndsArr ,
	                                                      ushort[] _depthPlayerData,ushort boundaryThreshVal)
	{
		Vector2 pixposMin=Vector2.zero;
		Vector2 pixposMax=Vector2.zero;
		if(jointPixPos0.y<jointPixPos1.y)
		{
			pixposMin=jointPixPos0;
			pixposMax=jointPixPos1;
		}
		else
		{
			pixposMin=jointPixPos1;
			pixposMax=jointPixPos0;
		}
		
		int minY=(int)pixposMin.y;
		int maxY=(int)pixposMax.y;
		int minX=(int)pixposMin.x;
		int maxX=(int)pixposMax.x;
		
		float XAddedValue=((float)(maxX-minX))/((float)(maxY-minY));
		
		//Debug.Log("XAddedValue----------------------------------------------"+XAddedValue.ToString() );
		float Xaccu=(float)minX;
		
		
		
		Vector2 resultMin = GetContourMinEnd(depthW,depthH,(int)pixposMin.x,  (int)pixposMin.y, 
		                                     _depthPlayerData,boundaryThreshVal);
		
		//		Debug.Log("beginning pixPosMin  " + pixposMin.x.ToString()  );
		//		
		//		Debug.Log("beginning resultMin  " + resultMin.x.ToString()  );
		
		Vector2 resultMax = GetContourMaxEnd (depthW,depthH,(int)pixposMin.x, (int)pixposMin.y, 
		                                      _depthPlayerData,boundaryThreshVal);
		int currWidth=(int)Math.Abs(resultMin.x-resultMax.x)  ;
		for(int i=minY;i<maxY;i++)
		{
			int tmpy=i;
			int tmpx=(int)Xaccu;
			Vector2 end0 = GetContourMinEnd (depthW,depthH,tmpx,tmpy, 
			                                 _depthPlayerData,boundaryThreshVal);
			
			//Debug.Log("end0  " + end0.x.ToString()  );
			
			Vector2 end1 = GetContourMaxEnd (depthW,depthH,tmpx,tmpy, 
			                                 _depthPlayerData,boundaryThreshVal);		
			
			int tmpWW=0;
			
			if((end0.x>20)&&(end0.x< depthW-20)&&
			   (end1.x>20)&&(end1.x< depthW-20)
			   )
			{
				//in this function, we store all ends poses in a range of heights. 
				//the 3 entries of the vector3 are  ( minendX, maxendX, Y)
				thickEndsArr.Add(new Vector3(end0.x, end1.x,tmpy)  );
			}

		}
	
//		if(minEnd.x<50)
//		{
//			int playeridx0=	(_depthPlayerData  [((int)(jointPixPos0.y)) *depthW +((int)(jointPixPos0.x))]) & 7;
//			int playeridx1=	(_depthPlayerData  [((int)(jointPixPos1.y)) *depthW +((int)(jointPixPos1.x))]) & 7;
//			
//			Debug.Log("-------------------------------------------------------player idx  "+playeridx0.ToString()+"----------:   "+playeridx1.ToString());
//			Debug.Log("-------------------------------------------------------result Ends MIn  "+((int)(minEnd.x)).ToString()+"-------Max:   "+((int)(maxEnd.x)).ToString());
//		}
//		
//		if(maxEnd.x>depthW- 50)
//		{
//			int playeridx0=	(_depthPlayerData  [((int)(jointPixPos0.y)) *depthW +((int)(jointPixPos0.x))]) & 7;
//			int playeridx1=	(_depthPlayerData  [((int)(jointPixPos1.y)) *depthW +((int)(jointPixPos1.x))]) & 7;
//			
//			Debug.Log("-------------------------------------------------------player idx  "+playeridx0.ToString()+"----------:   "+playeridx1.ToString());
//			Debug.Log("-------------------------------------------------------result Ends max  "+((int)(minEnd.x)).ToString()+"-------Max:   "+((int)(maxEnd.x)).ToString());
//		}
//		
	}






















	public static bool DoesPixBelongToPlayers(int depthW, int depthH,  int pixposx, int pixposy,  ushort[] _depthPlayerData  )
	{
		if((	_depthPlayerData  [pixposy *depthW +pixposx] & 7)>0)
		{
			return true;
		}

		return false;
	}


	public static  float CalculateChestGirth (float chestWideness, float chestThickness, float  chestRatioSquare )
	{
		return CalculateChestGirthRealize ( chestWideness,  chestThickness,   chestRatioSquare );

	}


	private static  float CalculateChestGirthRealize (float chestWideness, float chestThickness, float  chestRatioSquare )
	{
		//using the way of ellipse perimeter
		//return (2*Mathf.PI*(chestThickness/2)+4f*Mathf.Abs((chestWideness-chestThickness )/2))*chestRatio;

		//method before  11 25
		//using the way of square perimeter
		
		//the multiplying value multiplied on the square perimeter is changed according to the ratio
		//of width and thickness.
		//if the ratio of wide and thick is 1 the value is close to 0.9
		//if  1.5, close to 0.84;
		//after that  we  will multiplied by another  multi value


		//before   12 05
//		float ratioForManWomenChestDiff=1f; //Woman has a more thick side. if the orig girth is same, which means 
//		                   //the womenthe front is smaller and side is thicker , the final girth for woman will be smaller. 
//		                   //For the weight for thick is 1.14 but for wide is 2.
////		//ratio of width and thickness
//		float WTratio=chestWideness/chestThickness;
//		//float bigratio=0.91f, smallratio=0.82f;
//		float bigratio=1.01f, smallratio=0.91f;  //This setting is for different of man and woman . 
//		
//		if(WTratio<=1f)  //more round
//		{
//			ratioForManWomenChestDiff=bigratio;
//		}
//		else if(WTratio>1.45f)  // more flat
//		{
//			ratioForManWomenChestDiff=smallratio;
//		}
//		else
//		{
//			float a0= Mathf.Abs((WTratio-1f)/0.45f);
//			ratioForManWomenChestDiff=bigratio-a0*(bigratio-smallratio);
//		}
////		return Mathf.Abs (2 * (chestThickness + chestWideness)) *ratio* chestRatioSquare;
//
//		//(3.14*thick+(2*(wide-thick)))*ratio  = ��1.14*thick+2*wide��*ratio
//		
//		float origGirth=(2 * Mathf.PI * (chestThickness / 2) + 4f * Mathf.Abs ((chestWideness - chestThickness) / 2));
//		float extraRatio=1f;
//		if(origGirth>0.95f)
//		{
//			extraRatio=(1+0.1f*(origGirth-0.95f));
//			
//		}
//		else
//		{
//			extraRatio=(1-0.6f*(0.95f-origGirth))*ratioForManWomenChestDiff;	 //for thick difference of woman and man		
//		}
//
//
//		  return origGirth *extraRatio*chestRatioSquare;



		//After  12  05   Using  4  meters
		//Pay attention, this should be  in  the unit of cm.
		float wwcm=chestWideness*100f;
		float wthcm=chestThickness*100f;
		
		float girth= ((0.103f*wwcm*wwcm)+(-7.689f*wwcm)+(-0.257f*wthcm*wthcm)+(16.084f*wthcm))/100f;
		return  girth;

	}


	public static float CalculateWaistGirth (float waistWideness, float waistThickness , float  waistRatio  )
	{
		return CalculateWaistGirthRealize ( waistWideness,  waistThickness ,   waistRatio  );
	}
	
	private static float CalculateWaistGirthRealize (float waistWideness, float waistThickness , float  waistRatio  )
	{
		
		//(3.14*thick+(2*(wide-thick)))*ratio  = ��1.14*thick+2*wide��*ratio		
//		float origGirth=(2 * Mathf.PI * (waistThickness / 2) + 4f * Mathf.Abs ((waistWideness - waistThickness) / 2));
//		float extraRatio=1f;
//		if(origGirth>0.85f)
//		{
//			extraRatio=1+0.7f*(origGirth-0.85f);
//			
//		}
//		else
//		{
//			//The girth for very small guy is too small.
//			//So we reduce the para for small guy from 0.75  to  0.4
//			//extraRatio=1-0.75f*(0.85f-origGirth);			
//			extraRatio=1-0.4f*(0.85f-origGirth);			
//			
//		}
//		
//		
//		//since  11 29 ,
//		//we use 2 different way to balance the result of waist girth
//		//One way of ellipse and ratio which is origGirth * waistRatio*extraRatio
//		//another is the 0.9 * the square girth. 
//		//finally we use the average of this 2.
//		
//		float squaregirth = (waistWideness + waistThickness) * 2 * 0.9f;
//		
//		
//		
//		return (origGirth *extraRatio+squaregirth)* waistRatio/2f ;



		//Method since 1130  Using a way of statistics which use least square value for several tests.
		// the coeffecient value is got by 2 square of least square method  


		//Pay attention, this should be  in  the unit of cm.
		float wwcm=waistWideness*100f;
		float wthcm=waistThickness*100f;


		//Since 12  
		//float girth= ((-0.105f*wwcm*wwcm)+(8.105f*wwcm)+(0.183f*wthcm*wthcm)+(-6.927f*wthcm))/100f;



		//Since  12  19  using  a  table
		int wideidx = Mathf.Clamp((int)Mathf.Round (wwcm - 26),0,10);  
		int thickidx = Mathf.Clamp((int)Mathf.Round (wthcm-18),0,14);

		float girth= (waistTable[wideidx,thickidx])/100f;
		//Debug.Log("Waist------------"+"wid: "+waistWideness.ToString()+"  thick "+ waistThickness.ToString()+" girth  "+girth.ToString() );
		return  girth;
	}




	public static  float CalculateHipsGirth (float hipsWideness, float hipsThickness , float  hipsRatio)
	{
		return  CalculateHipsGirthRealize ( hipsWideness,  hipsThickness ,   hipsRatio);
	}

	private static  float CalculateHipsGirthRealize (float hipsWideness, float hipsThickness , float  hipsRatio)
	{

//    method before 1205  
//		float origHipGirth=(2 * Mathf.PI * (hipsThickness / 2) + 4f * Mathf.Abs ((hipsWideness - hipsThickness) / 2)) * hipsRatio;
//		float extraRatio=1f;
//		if(origHipGirth>1f)
//		{
//			extraRatio=(1+0.7f*(origHipGirth-1f));
//			
//		}
//		else
//		{
//			extraRatio=(1-0.5f*(1f-origHipGirth));	 		
//		}

	//	return origHipGirth*extraRatio;


// method after  12 05, using 4 parameters.
		//Pay attention, this should be  in  the unit of cm.
//		float wwcm=hipsWideness*100f;
//		float wthcm=hipsThickness*100f;
//				
//		float girth= ((-0.205f*wwcm*wwcm)+(16.449f*wwcm)+(0.385f*wthcm*wthcm)+(-18.687f*wthcm))/100f;



//method  using a hips table
		float wwcm=hipsWideness*100f;
		float wthcm=hipsThickness*100f;
		int wideidx = Mathf.Clamp((int)Mathf.Round (wwcm - 30),0,12);  
		int thickidx = Mathf.Clamp((int)Mathf.Round (wthcm-20),0,12);
		
		float girth= (HipsTable[wideidx,thickidx])/100f;

		//Debug.Log("Waist------------"+"wid: "+waistWideness.ToString()+"  thick "+ waistThickness.ToString()+" girth  "+girth.ToString() );
		return  girth;

	}






	public static float GetShoulderWidth(Vector3 shoulder0, Vector3 shoulder1 )
	{
		return GetShoulderWidthRealize(shoulder0, shoulder1 );
	}

	private static float GetShoulderWidthRealize(Vector3 shoulder0, Vector3 shoulder1 )
	{
		float shoulderDistance=Vector3.Distance(shoulder0, shoulder1);

		return shoulderDistance*1.4f;		
	}


	public static float GetArmLength(Vector3 shoulder0, Vector3 shoulder1, Vector3 hand0, Vector3 hand1 )
	{
		return GetArmLengthRealize( shoulder0,  shoulder1,  hand0,  hand1 );
	}
	
	private static float GetArmLengthRealize(Vector3 shoulder0, Vector3 shoulder1, Vector3 hand0, Vector3 hand1 )
	{
		float armlen0=Vector3.Distance(shoulder0, hand0);
		float armlen1=Vector3.Distance(shoulder1, hand1);
		
		return  (armlen0+armlen1)/2f*1.2f ;		
	}


	public static float GetLegLength(Vector3 hip0, Vector3 hip1, Vector3 feet0, Vector3 feet1 )
	{
		return GetLegLengthRealize(  hip0, hip1, feet0,    feet1 );
	}
	
	private static float GetLegLengthRealize(Vector3 hip0,Vector3 hip1, Vector3 feet0,  Vector3 feet1  )
	{
		float leglen0=Vector3.Distance(hip0, feet0);
		float leglen1=Vector3.Distance(hip1, feet1);
		
		return  (leglen0+leglen1)/2f ;		
	}
	

	public static float GetGirth2(float frontArcLen, float frontChordLen, float frontChordThick, float bodyThickness, float remainGirthRatio0,float remainGirthRatio1)
	{
		return GetGirth2Realize(frontArcLen,  frontChordLen, frontChordThick, bodyThickness, remainGirthRatio0,remainGirthRatio1);			
	}

	private static float GetGirth2Realize(float frontArcLen, float frontChordLen, float frontChordThick, float bodyThickness, float remainGirthRatio0,float remainGirthRatio1)
	{
		if(FrontMeaMgr.EnableFunction)
		{
		float SideBackLen=bodyThickness-frontChordThick;
		if(SideBackLen<0)
		{
			SideBackLen=0f;
		}
		
			return   (frontArcLen *remainGirthRatio0+  (SideBackLen*2  + frontChordLen)*remainGirthRatio1) ;	
		}
		else
		{
			Debug.LogError("Get girth failed. Network number check failed.");
			return 0f;
		}
	}






	//This  func will remove the first 1/3 and last 1/3 of the arr and return the avg value of the middle 1/3 part
	//Usually the entry in the input arr   are  all   ints.
	//This is for getting the final  overall  value  of  left boundary  ,  left sharp  contour of body and left body boundary
	public static int GetAvgValueOfMiddlePart(ArrayList arr)
	{
		if(arr.Count>3)
		{
			arr.Sort();
			//			for(int i=0;i<arr.Count;i++)
			//			{
			//				Debug.Log("current value  :  "+i.ToString()+"   "+ ((int)( arr[i])).ToString());
			//			}
			
			int onethirdCount=arr.Count/3;
			for(int i=0;i<onethirdCount;i++)
			{
				arr.RemoveAt(0);
			}
			
			int halfCount=arr.Count/2;
			for(int i=0;i<halfCount;i++)
			{
				arr.RemoveAt(arr.Count-1);
			}
			
			return GetIntAveOfArraylist(arr);
		}
		else if(arr.Count==0)
		{
			Debug.LogError("The count of input arraylist is 0");
			return 0;
		}
		else
		{
			Debug.LogError("The count of input arraylist is smaller than 3");
			return GetIntAveOfArraylist(arr);
			
		}
		
	}
	
	
	
	public static int GetIntAveOfArraylist(ArrayList arr)
	{
		if(arr.Count>0)
		{
			int sum=0;
			foreach(int v in arr)
			{
				sum+=v;
			}
			
			return (int)((float)sum/(float)(arr.Count));
		}
		
		Debug.LogError("Zero value in Arr");
		return 0;
	}
	
	
	
	
	
	public static float GetFloatAveOfArraylist(ArrayList arr)
	{
		if(arr.Count>0)
		{
			float sum=0f;
			foreach(float v in arr)
			{
				sum+=v;
			}
			
			return sum/(float)(arr.Count);
		}
		
		Debug.LogError("Zero value in Arr");
		return 0f;
	}
	
	





















#endregion


}
